#pragma once
#include <iostream>
#include "Socket.hpp"
#include <memory>
#include "InetAddr.hpp"
#include "Connection.hpp"
#include "Epoller.hpp"
#include "HandlerConnection.hpp"
using namespace std;
using namespace socket_ns;
// 链接管理模块
class Listener
{
public:
    Listener(uint16_t port, HandlerConnection &hc)
        : _port(port),
          _listensock(make_unique<TcpSocket>()),
          _hc(hc)
    {
        // 创建listen sock fd
        InetAddr addr("0.0.0.0", _port);
        // 获取listen sock套接字
        _listensock->BuildListenSocket(addr);
        LOG(DEBUG, "listen sock fd:%d\n", _listensock->SockFd());
    }
    // listen sock获取链接
    void Accepter(Connection *conn)
    {
        // 这里需要一直获取链接，因为是ET模式，只会通知一次,所以这里要一直不断的获取链接
        while (true)
        {
            InetAddr clientaddr; // 客户端信息
            int code = 0;        // 错误码
            int sockfd = _listensock->Accepter(&clientaddr, &code);
            if (sockfd >= 0)
            {
                // 获取链接成功
                // 添加链接到Reactor
                conn->_R->AddConnection(
                    sockfd,
                    EPOLLIN | EPOLLET,
                    bind(&HandlerConnection::HandlerRecv, &_hc, placeholders::_1),  // 读事件处理方法
                    bind(&HandlerConnection::HandlerSend, &_hc, placeholders::_1),  // 写事件处理方法
                    bind(&HandlerConnection::HandlerExcept, &_hc, placeholders::_1) // 异常事件处理方法
                );
            }
            else
            {
                // 获取链接失败
                if (code == EWOULDBLOCK || code == EAGAIN)
                {
                    // 底层已经获取到所有链接了
                    LOG(DEBUG, "底层已经获取到所有的链接了\n");
                    break;
                }
                else if (code == EINTR)
                {
                    // 此次获取链接被信号中断了
                    LOG(DEBUG, "底层获取链接被信号中断了\n");
                    continue;
                }
                else
                {
                    // 获取链接失败
                    LOG(WARNING, "底层获取链接失败\n");
                    break;
                }
            }
        }
    }
    // 获取sockfd
    int Sockfd()
    {
        return _listensock->SockFd();
    }
    ~Listener()
    {
        _listensock->Close();
    }

private:
    uint16_t _port;                 // 端口号
    unique_ptr<Socket> _listensock; // 套接字指针
    HandlerConnection &_hc;         // 业务处理类
};